#ifndef _REFCHAR_H
#define _REFCHAR_H
#include <tool/ydefine.h>
#include <tool/ystr.h>
#include <tool/ypropertiesFile.h>

/** Data & function pointer struct, use externally */
typedef struct refChar *refChar;
/** Data struct, use internally */
typedef struct refCharData *refCharData;

/** Struct of reference character data & function pointers */
struct refChar {
  /*--- data ---*/
  refCharData d;
  /*--- function pointers ---*/
  /** Set <code>refChar</code>'s <code>strFn</code>.
  If <code>strFn</code> is already created, 
  this action will be ignored and <code>false</code> will be returned.
  <code>refChar</code> will NOT free the memory of 
  <code>strFn</code> that is created externally, 
  you MUST free this yourself.
  @param ref the <code>refChar</code> to use.
  @param strFn pass in the <code>strFn</code> to use.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setStrFn)(refChar ref, strFn strFn);
  /** Free a reference char struct, free up the memory.
  @param refP pass in the address of 
    reference char struct pointer to be free.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*free)(refChar *refP);
  /* specific operation */
  /** Add a word list with their page number into <code>refChar</code>.
  @param ref pass in the reference char struct.
  @param wordArray the word array that contains the word list.
  @param wordArrayLen the length of the <code>wordArray</code>
  @param pageNum the page number to add.
  @param forceAdd forcing the words in <code>wordArray</code> to be added. 
    Against any setting such as <code>ignoreNumbers</code> 
    (overide value using <code>setIgnoreNumbers(refChar, boolean)</code>)
    or <code>lesserFirst</code> 
    (overide value using <code>setLesserFirst(refChar, boolean)</code>)
    However empty string or word is NOT added, 
    even if <code>forceAdd</code> is set to <code>true</code>.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*add)(refChar ref, char **wordArray, 
      const unsigned char wordArrayLen, 
      const char *pageNum, const boolean forceAdd);
  /** Add a word with its' page number into <code>refChar</code>.
  @param ref pass in the reference char struct.
  @param aWord the word.
  @param pageNum the page number to add.
  @param forceAdd forcing the words in <code>wordArray</code> to be added. 
    Against any setting such as <code>ignoreNumbers</code> 
    (overide value using <code>setIgnoreNumbers(refChar, boolean)</code>)
    or <code>lesserFirst</code> 
    (overide value using <code>setLesserFirst(refChar, boolean)</code>)
    However empty string or word is NOT added, 
    even if <code>forceAdd</code> is set to <code>true</code>.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*addWord)(refChar ref, char *aWord,
      const char *pageNum, const boolean forceAdd);
  /** Write the current string representation of <code>refChar</code>
  according to the requirement to the stream.
  @param ref pass in the reference char struct.
  @param stream the output stream to write to.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*fwrite)(const refChar ref, FILE *stream);
  /** Change <code>ignoreNumbers</code> value.
  Default <code>ignoreNumbers</code> is set to <code>true</code>. 
  If set to <code>true</code> <code>refChar</code> will ignore words 
  that are made up all of digits. Otherwise set to <code>false</code> will 
  include words that are made all of digits.
  @param ref pass in the reference char struct.
  @param ignoreNumbers to include numbers set this to <code>false</code> 
    otherwise set to <code>true</code> to ignore the numbers.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setIgnoreNumbers)(refChar ref, const boolean ignoreNumbers);
  /** Change <code>lesserFirst</code> value.
  Default <code>lesserFirst</code> is set to <code>true</code>. 
  If set to <code>true</code> <code>refChar</code> 
  will return list of words whose ASCII value is lesser at the front. 
  Otherwise set to <code>false</code> <code>refChar</code> 
  will return list of words whose ASCII value is greater at the front. 
  @param ref pass in the reference char struct.
  @param lesserFirst to sort list by greater first set this to <code>false</code> 
    otherwise set to <code>true</code> to place lesser first.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setLesserFirst)(refChar ref, const boolean lesserFirst);
  /** Set the propertiesFile to use.
  @param ref pass in the reference char struct.
  @param conf the propertiesFile to use, 
    pass in <code>NULL</code> to use none.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setPropertiesFile)(refChar ref, propertiesFile conf);
  /** Returns the number of elements in this <code>refChar</code>.
  @param ref pass in the reference char struct.
  @return Returns the number of elements in this 
    <code>refChar</code> or -1 if failure.
  */
  int (*size)(const refChar ref);
};

/** Create a reference char struct for use which has the 
letters A to Z, a to z and '_'.

Default <code>ignoreNumbers</code> is set to <code>true</code>. 
If set to <code>true</code> <code>refChar</code> will ignore words 
that are made up all of digits. Otherwise set to <code>false</code> will 
include words that are made all of digits.

Default <code>lesserFirst</code> is set to <code>true</code>. 
If set to <code>true</code> <code>refChar</code> 
will return list of words whose ASCII value is lesser at the front. 
Otherwise set to <code>false</code> <code>refChar</code> 
will return list of words whose ASCII value is greater at the front. 
@return a working newly created reference char struct 
  or <code>NULL</code> if failure.
*/
refChar refChar_create(void);
/** Create a reference char struct for use which has the 
letters A to Z, a to z and '_'.

Default <code>ignoreNumbers</code> is set to <code>true</code>. 
If set to <code>true</code> <code>refChar</code> will ignore words 
that are made up all of digits. Otherwise set to <code>false</code> will 
include words that are made all of digits.

Default <code>lesserFirst</code> is set to <code>true</code>. 
If set to <code>true</code> <code>refChar</code> 
will return list of words whose ASCII value is lesser at the front. 
Otherwise set to <code>false</code> <code>refChar</code> 
will return list of words whose ASCII value is greater at the front. 
@param conf the propertiesFile to use.
@return a working newly created reference char struct 
  or <code>NULL</code> if failure.
*/
refChar refChar_createWith(propertiesFile conf);

#endif /* _REFCHAR_H */
